#ifndef GAME_ANIMATION_TEST_SHADER_H
#define GAME_ANIMATION_TEST_SHADER_H
//
// Game Animation.
// Copyright (C) 2007 Department of Computer Science, University of Copenhagen
//
#include <animation/configuration.h>

#include <OpenTissue/utility/Cg/cg_program.h>
#include <OpenTissue/image/image.h>
#include <OpenTissue/image/io/image_read.h>
#include <OpenTissue/image/io/image_write.h>
#include <OpenTissue/texture/texture2D.h>
#include <OpenTissue/image/util/make_noise.h>
#include <OpenTissue/image/util/alpha_modulation.h>

namespace animation
{

  /**
  * The Test Shader.
  * This class setups (and shutdowns) the rendering before draw the geometry of the grass layer.
  *
  */
  class TestShader
  {
  protected:

    OpenTissue::CgProgram                                m_vertex_program;
    OpenTissue::CgProgram                                m_fragment_program;
    boost::shared_ptr<OpenTissue::Image<unsigned char> > m_puff_image;
    OpenTissue::texture2D_pointer                        m_puff_texture;

  public:

    /**
    * Pre-rendering.
    *
    * @param rightx          The x-coordinate of the camera right vector in WCS.
    * @param righty          The y-coordinate of the camera right vector in WCS.
    * @param rightz          The z-coordinate of the camera right vector in WCS.
    * @param upx             The x-coordinate of the camera up vector in WCS.
    * @param upy             The y-coordinate of the camera up vector in WCS.
    * @param upz             The z-coordinate of the camera up vector in WCS.
    * @param time            The current time, used to animate grass movement.
    * @param visible_range   Determines how far away one can see grass clumps before the fade out into the background.
    */
    void pre_render (
      float rightx
      , float righty
      , float rightz
      , float upx
      , float upy
      , float upz
      , float time
      , float visible_range
      )
    {
      //--- Load textures if they are not allready loaded
      if(!m_puff_image)
      {
        m_puff_image.reset( new OpenTissue::Image<unsigned char>() );
        image_read(demo_path + "landscape/data/grass_pack.png",*m_puff_image);

        OpenTissue::Image<unsigned char> alpha(m_puff_image->width(),m_puff_image->height(), 1);
        make_noise(alpha,128.0,255.0);
        alpha_modulation(*m_puff_image,alpha);

        m_puff_texture = m_puff_image->create_texture(GL_RGBA);
      }

      if(!m_vertex_program.is_program_loaded())
        m_vertex_program.load_from_file(OpenTissue::CgProgram::vertex_program,demo_path + "../animation/vp_test.cg");

      float light_x = 0.57735026918962576450914878050225;
      float light_y = -0.57735026918962576450914878050225;
      float light_z = 0.57735026918962576450914878050225;

      m_vertex_program.set_float_param("light_vec",           light_x, light_y, light_z);
      m_vertex_program.set_float_param("right",               rightx, righty, rightz);
      m_vertex_program.set_float_param("up",                  upx,    upy,    upz);
      m_vertex_program.set_float_param("time",                time);
      m_vertex_program.set_float_param("visible_range",       visible_range);
      m_vertex_program.set_modelview_projection_matrix();

      //--- load fragment program
      if(!m_fragment_program.is_program_loaded())
        m_fragment_program.load_from_file(OpenTissue::CgProgram::fragment_program,demo_path + "../animation/fp_test.cg");

      m_fragment_program.set_input_texture("puff_texture",m_puff_texture);

      m_fragment_program.enable();
      m_vertex_program.enable();

      //--- Setup openGL state
      glEnable(GL_MULTISAMPLE_ARB);              //--- KE 2005.10.23: Need a ge78000:-(
      glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE_ARB);
      glEnable(GL_BLEND);
      glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
      glEnable(GL_ALPHA_TEST);
      glAlphaFunc(GL_GREATER, 0);
      glDepthMask(0);
    }

    void post_render()
    {
      glDisable(GL_MULTISAMPLE_ARB);             //--- KE 2005.10.23: Need a ge78000:-(
      glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE_ARB);
      glDisable(GL_ALPHA_TEST);
      glDisable(GL_BLEND);
      glDepthMask(1);

      m_fragment_program.disable();
      m_vertex_program.disable();
    }
  };

} // namespace animation

// GAME_ANIMATION_TEST_SHADER_H
#endif
